<?php

declare(strict_types=1);

namespace chixian\Libraries\Middleware;

use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\SimpleCache\CacheInterface;
use chixian\Libraries\Exception\MiddlewareException;

class AuthMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected ContainerInterface $container;

    /**
     * @var CacheInterface
     */
    protected $cache;

    /** @var int 时差 */
    protected $jetLagSec = 120;

    /** @var string 约定标识 */
    protected $sign = '';

    /**
     *
     * AuthMiddleware constructor.
     * @param ContainerInterface $container
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->sign = config('auth.auth_sign');
        $this->cache = $container->get(CacheInterface::class);
    }

    /**
     * api auth 验证
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // 参数
        if (!$request->hasHeader('Api-Token') || !$request->hasHeader('Api-Timestamp') || !$request->hasHeader('Api-Random-Str')) {
            throw new MiddlewareException('api-token api-timestamp api-random-str 不能为空');
        }
        $apiToken = $request->getHeaderLine('Api-Token');
        $apiTimestamp = $request->getHeaderLine('Api-Timestamp');
        $apiRandomStr = $request->getHeaderLine('Api-Random-Str');
        // 时差
        if (abs(time() - (int)$apiTimestamp) >= $this->jetLagSec) {
            throw new MiddlewareException('您的手机时间并不是当前北京时间,为了更好的体验请修改下时间。');
        }
        // 签名
        $arr = [$this->sign, $apiTimestamp, $apiRandomStr];
        sort($arr);
        if ($apiToken != md5(implode('', $arr))) {
            throw new MiddlewareException('Api-Token 错误');
        }
        // 时效
        if ($this->cache->get('captcha:auth:' . $apiToken)) {
            throw new MiddlewareException('已经提交过了,请不要重复提交。');
        } else {
            $this->cache->set('captcha:auth:' . $apiToken, 1, 60);
        }

        return $handler->handle($request);
    }
}